home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / od-amiga / ami-disk.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  13KB  |  472 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * ami-disk.c: Creates pseudo dev: handler. Copy tracks to rawfile 
  5.   * (used in zfile.c).
  6.   * 
  7.   * 08/06/97: Modified to avoid a spilled registers error message
  8.   *           when used with the new fd2inline convention.
  9.   * 
  10.   * Copyright 1996 Samuel Devulder.
  11.   */
  12.  
  13. /****************************************************************************/
  14.  
  15. #include <exec/execbase.h>
  16. #include <exec/memory.h>
  17. #include <exec/devices.h>
  18. #include <exec/io.h>
  19.  
  20. #include <dos/dos.h>
  21.  
  22. #include <devices/trackdisk.h>
  23.  
  24. /* This should cure the spilled-register problem. An other solution is to */
  25. /* compile with -O2 instead of -O3 */
  26. #define NO_INLINE_STDARGS
  27. #define __NOINLINES__
  28.  
  29. #include <proto/exec.h>
  30. #ifndef __SASC
  31. #include <proto/alib.h>
  32. #endif
  33. #include <proto/dos.h>
  34.  
  35. /****************************************************************************/
  36.  
  37. #include "sysconfig.h"
  38. #include "sysdeps.h"
  39.  
  40. #include <ctype.h>
  41. #include <signal.h>
  42.  
  43. #include "config.h"
  44. #include "options.h"
  45. #include "memory.h"
  46. #include "custom.h"
  47. #include "keyboard.h"
  48. #include "keybuf.h"
  49. #include "disk.h"
  50. #include "debug.h"
  51. #include "gui.h"
  52.  
  53. /****************************************************************************/
  54.  
  55. char *amiga_dev_path  = "DEV:";
  56. char *ixemul_dev_path = "/dev/";
  57.  
  58. int readdevice(char *name, char *dst);
  59. void initpseudodevices(void);
  60. void closepseudodevices(void);
  61. char *to_unix_path(char *s);
  62. char *from_unix_path(char *s);
  63. void split_dir_file(char *src, char **dir, char **file);
  64. static void myDoIO(struct IOStdReq *ioreq, LONG CMD, LONG FLAGS, LONG OFFSET, 
  65.                    LONG LENGTH, LONG DATA);
  66.  
  67. /****************************************************************************/
  68.  
  69. static char *pseudo_dev_path = "T:DEV";
  70.  
  71. static char pseudo_dev_created  = 0;
  72. static char pseudo_dev_assigned = 0;
  73. static char dfx_done[4];
  74.  
  75. static int device_exists(char *device_name, int device_unit);
  76. static int dev_inhibit(char *dev,int on);
  77. static void set_req(int ok);
  78.  
  79. /****************************************************************************/
  80. /* support routines to handle unix filename convention 
  81.  */
  82. char *to_unix_path(char *s)
  83. {
  84.     char *t,*r,*u;
  85.     int l;
  86.  
  87. #ifndef __GNUC
  88.     return my_strdup(s);
  89. #endif
  90.  
  91.     for(u=s,l=0;*u;++u,++l) if(*u=='/' || *u==':') l+=2;
  92.  
  93.     r = t = malloc(1+l);
  94.     if(!r) return NULL;
  95.  
  96.     for(u=s;*u && *u!=':';++u);
  97.     if(*u) {
  98.         *t++='/';
  99.         while(*s!=':') *t++=*s++;
  100.         *t++='/';++s;
  101.     }
  102.     while(*s=='/') {*t++='.';*t++='.';*t++=*s++;}
  103.     while(*s) {
  104.         if(s[0]=='/' && s[1]=='/') {*t++=*s++;*t++='.';*t++='.';*t++=*s++;}
  105.         else *t++=*s++;
  106.     }
  107.     *t='\0';
  108.     return r;
  109. }
  110.  
  111. /****************************************************************************/
  112.  
  113. char *from_unix_path(char *s)
  114. {
  115.     char *t,*r;
  116.  
  117.     r = t = malloc(strlen(s)+1);
  118.     if(!r) return NULL;
  119. #ifndef __GNUC__
  120.     strcpy(r,s);
  121.     return r;
  122. #endif
  123.  
  124.     if(*s=='/') {
  125.         ++s;
  126.         while(*s && *s!='/') *t++=*s++;
  127.         if(*s=='/') {*t++=':';++s;}
  128.     }
  129.  
  130.     while(*s) {
  131.         if(s[0]=='.' && s[1]=='.') s+=2;
  132.         else *t++=*s++;
  133.     }
  134.  
  135.     *t='\0';
  136.  
  137.     return r;
  138. }
  139.  
  140. /****************************************************************************/
  141.  
  142. void split_dir_file(char *src, char **dir, char **file)
  143. {   /* note: src is freed() */
  144.     char *s=src;
  145.  
  146.     while(*s) ++s;
  147.     while(s>src && (*s!=':' && *s!='/')) --s;
  148.     if(*s==':' || *s=='/') {
  149.         *file = my_strdup(s+1);
  150.         s[1]  = '\0';
  151.         *dir  = my_strdup(src);
  152.         free(src);
  153.     } else {
  154.         *file = src;
  155.         *dir  = my_strdup("");
  156.     }
  157. }
  158.  
  159. /****************************************************************************/
  160. /*
  161.  * Creates peudo DEV:DFx files.
  162.  */
  163. void initpseudodevices(void)
  164. {
  165.     ULONG lock;
  166.     int i;
  167.  
  168.     pseudo_dev_created  = 0;
  169.     pseudo_dev_assigned = 0;
  170.     for(i=0;i<4;++i) dfx_done[i]=0;
  171.  
  172.     /* check if dev: already exists */
  173.     set_req(0);lock = Lock(amiga_dev_path,SHARED_LOCK);set_req(1);
  174.     if(!lock) {
  175.         char name[80];
  176.         set_req(0);lock = Lock(pseudo_dev_path,SHARED_LOCK);set_req(1);
  177.         if(!lock) {
  178.             /* create it */
  179.             lock = CreateDir(pseudo_dev_path);
  180.             if(!lock) goto fail;
  181.             UnLock(lock);lock = Lock(pseudo_dev_path,SHARED_LOCK);
  182.             pseudo_dev_created = 1;
  183.         }
  184.         strcpy(name,amiga_dev_path);
  185.         if(*name && name[strlen(name)-1]==':') name[strlen(name)-1]='\0';
  186.         if(!AssignLock(name,lock)) {UnLock(lock);goto fail;}
  187.         /* the lock is the assign now */
  188.         pseudo_dev_assigned = 1;
  189.     } else UnLock(lock);
  190.  
  191.     /* Create the dev:DFi entry */
  192.     for(i=0;i<4;++i) if(device_exists("trackdisk.device",i)) {
  193.         ULONG fd;
  194.         char name[80];
  195.  
  196.         sprintf(name,"%sDF%d",amiga_dev_path,i);
  197.         fd = Open(name,MODE_NEWFILE);
  198.         if(fd) {Close(fd);dfx_done[i]=1;}
  199.     }
  200.  
  201.     return;
  202.  fail:
  203.     fprintf(stderr,"Failed to create pseudo dev: entry!\n");
  204. }
  205.  
  206. /****************************************************************************/
  207. /*
  208.  * Cleanup pseudo DEV:DFx
  209.  */
  210. void closepseudodevices(void)
  211. {
  212.     int i;
  213.     for(i=0;i<4;++i) if(dfx_done[i]) {
  214.         char name[80];
  215.         sprintf(name,"%sDF%d",amiga_dev_path,i);
  216.         DeleteFile(name);
  217.         dfx_done[i] = 0;
  218.     }
  219.  
  220.     if(pseudo_dev_assigned) {
  221.         char name[80];
  222.         strcpy(name,amiga_dev_path);
  223.         if(*name && name[strlen(name)-1]==':') name[strlen(name)-1]='\0';
  224.         AssignLock(name,NULL);
  225.         pseudo_dev_assigned = 0;
  226.     }
  227.  
  228.     if(pseudo_dev_created) {
  229.         DeleteFile(pseudo_dev_path);
  230.         pseudo_dev_created = 0;
  231.     }
  232. }
  233.  
  234. /****************************************************************************/
  235. /*
  236.  * Enable/Disable system requester
  237.  */
  238. static void set_req(int ok)
  239. {
  240.     static ULONG wd = 0;
  241.     struct Process *pr;
  242.     
  243.     pr = (void*)FindTask(NULL);
  244.     
  245.     if(pr->pr_Task.tc_Node.ln_Type != NT_PROCESS) return;
  246.     
  247.     if(ok)  {
  248.         pr->pr_WindowPtr = (APTR)wd;
  249.     }
  250.     else    {
  251.         wd = (ULONG)pr->pr_WindowPtr;
  252.         pr->pr_WindowPtr = (APTR)-1;
  253.     }
  254. }
  255.  
  256. /****************************************************************************/
  257. /*
  258.  * checks if a device exists
  259.  */
  260. static int device_exists(char *device_name, int device_unit)
  261. {
  262.     struct IOStdReq *ioreq  = NULL;
  263.     struct MsgPort  *port   = NULL;
  264.     int ret = 0;
  265.  
  266.     port = CreatePort(0, 0);
  267.     if(port) {
  268.         ioreq = CreateStdIO(port);        
  269.         if(ioreq) {
  270.             if(!OpenDevice(device_name,device_unit,(void*)ioreq,0)) {
  271.                 CloseDevice((void*)ioreq);
  272.                 ret = 1;
  273.             }
  274.             DeleteStdIO(ioreq);    
  275.         }
  276.         DeletePort(port);
  277.     }
  278.     return ret;
  279. }
  280.  
  281. /****************************************************************************/
  282. /*
  283.  * extract the device and unit form a filename.
  284.  */
  285. static void extract_dev_unit(char *name, char **dev_name, int *dev_unit)
  286. {
  287.     char *s;
  288.     if(tolower(name[0])=='d' && tolower(name[1])=='f' &&
  289.        name[2]>='0' && name[2]<='3' && name[3]=='\0') { 
  290.         /* DF0 */
  291.         *dev_unit = name[2]-'0';
  292.         *dev_name = strdup("trackdisk.device");
  293.     } else if((s = strrchr(name,'/'))) { 
  294.         /* trackdisk[.device]/0 */
  295.         *dev_unit = atoi(s+1);
  296.         *dev_name = malloc(1 + s-name);
  297.         if(*dev_name) {
  298.             strncpy(*dev_name, name, 1 + s-name);
  299.             (*dev_name)[s-name]='\0';
  300.         }
  301.     } else { 
  302.         /* ?? STRANGEDISK0: ?? */
  303.         *dev_unit = 0;
  304.         *dev_name = strdup(name);
  305.     }
  306.     if(*dev_name) {
  307.         char *s;
  308.         if(!(s = strrchr(*dev_name,'.'))) { 
  309.             /* .device is missing */
  310.             s = malloc(8+strlen(*dev_name));
  311.             if(s) {
  312.                 sprintf(s,"%s.device",*dev_name);
  313.                 free(*dev_name);
  314.                 *dev_name = s;
  315.             }
  316.         }
  317.     }
  318. }
  319.  
  320. /****************************************************************************/
  321. /*
  322.  * copy a device to a FILE*.
  323.  */
  324. static int raw_copy(char *dev_name, int dev_unit, FILE *dst)
  325. {
  326.     struct MsgPort  *port   = NULL;
  327.     struct IOStdReq *ioreq  = NULL;
  328.     int tracklen            = 512*11;
  329.     int retstatus           = 1;
  330.     int inhibited           = 0;
  331.     char *buffer            = NULL;
  332.     static char name[]      = {'D','F','0','\0'};
  333.  
  334.     if(!strcmp(dev_name, "trackdisk.device")) {
  335.         inhibited = 1;
  336.         name[2] = '0'+dev_unit;
  337.     }
  338.  
  339.     /* allocate system stuff */
  340.     if((port   = CreatePort(0, 0)))            {
  341.     if((ioreq  = CreateStdIO(port)))           {
  342.     if((buffer = AllocMem(tracklen, MEMF_CHIP))) {
  343.  
  344.     /* gain access to the device */
  345.     if(!OpenDevice(dev_name, dev_unit, (struct IORequest*)ioreq, 0)) {
  346.  
  347.     /* check if a disk is present */
  348.     myDoIO(ioreq, TD_CHANGESTATE, 0, -1, -1, -1);
  349.     if(!ioreq->io_Error && ioreq->io_Actual) {
  350.         fprintf(stderr,"No disk in %s unit %d !\n", dev_name, dev_unit);
  351.         retstatus = 0;
  352.     } else {
  353.         int tr = 0;
  354.         int write_protected = 0;
  355.         /* check if disk is write-protected:
  356.         myDoIO(ioreq, TD_PROTSTATUS, 0, -1, -1, -1);
  357.         if(!ioreq->io_Error && ioreq->io_Actual) write_protected = 1;
  358.         */
  359.  
  360.         /* inhibit device */
  361.         if(inhibited) inhibited = dev_inhibit(name,1);
  362.  
  363.         /* read tracks */
  364.         for(tr = 0; tr < 160; ++tr) {
  365.             printf("Reading track %2d side %d of %s unit %d  \r",
  366.                    tr/2, tr%2, dev_name, dev_unit);
  367.             fflush(stdout);
  368.             myDoIO(ioreq, CMD_READ, -1, tracklen*tr, tracklen, (LONG)buffer);
  369.             if(ioreq->io_Error) printf("Err. on\n");
  370.             if(fwrite(buffer, 1, tracklen, dst) != (unsigned int)tracklen) {
  371.                retstatus = 0; 
  372.                break;
  373.             }
  374.         }
  375.  
  376.         /* ok everything done! */
  377.         printf("                                                                        \r");
  378.         fflush(stdout);
  379.  
  380.         /* stop motor */
  381.         myDoIO(ioreq, TD_MOTOR, 0, -1, 0, -1);
  382.  
  383.         /* uninhibit */
  384.         if(inhibited) dev_inhibit(name,0);
  385.     }
  386.     CloseDevice((struct IORequest*)ioreq);   } else retstatus = 0;
  387.     FreeMem(buffer,tracklen);                } else retstatus = 0;
  388.     DeleteStdIO(ioreq);                      } else retstatus = 0;
  389.     DeletePort(port);                        } else retstatus = 0;
  390.     return retstatus;
  391. }
  392.  
  393. /****************************************************************************/
  394. /*
  395.  * Copy one raw disk to a file.
  396.  */
  397. int readdevice(char *name, char *dst) 
  398. {   /* erhm, I must admit this code is long and ugly! */
  399.     FILE *f = NULL;
  400.     char *device_name;
  401.     int   device_unit;
  402.     int   retstatus = 0;
  403. #ifdef HAVE_SIGACTION
  404.     struct sigaction oldsa;
  405.     int oldsa_valid;
  406.  
  407.     /* disable break */
  408.     oldsa_valid = (0==sigaction(SIGINT, NULL, &oldsa));
  409.     signal(SIGINT, SIG_IGN); /* <--- gcc complains about something */
  410.                              /* in there but I don't know why. */
  411. #endif
  412.  
  413.     /* get device name & unit */
  414.     extract_dev_unit(name, &device_name, &device_unit);
  415.     if(device_name) {
  416.         /* if no destination then just check if the device exists */
  417.         if(dst == NULL) 
  418.            retstatus = device_exists(device_name, device_unit);
  419.         else {
  420.             /* open dest file */
  421.             if((f = fopen(dst,"wb"))) {
  422.                 retstatus = raw_copy(device_name, device_unit, f);
  423.                 fclose(f);
  424.             }
  425.         }
  426.         free(device_name);           
  427.     }
  428.  
  429. #ifdef HAVE_SIGACTION
  430.     /* enable break */
  431.     if(oldsa_valid) sigaction(SIGINT, &oldsa, NULL);
  432. #endif
  433.  
  434.     return retstatus;
  435. }
  436.  
  437. /****************************************************************************/
  438.  
  439. static void myDoIO(struct IOStdReq *ioreq, LONG CMD, LONG FLAGS, LONG OFFSET, 
  440.                    LONG LENGTH, LONG DATA)
  441. {
  442.     if(CMD>=0)    ioreq->io_Command = CMD;
  443.     if(FLAGS>=0)  ioreq->io_Flags   = FLAGS;
  444.     if(OFFSET>=0) ioreq->io_Offset  = OFFSET;
  445.     if(LENGTH>=0) ioreq->io_Length  = LENGTH;
  446.     if(DATA>=0)   ioreq->io_Data    = (void*)DATA;
  447.     DoIO((struct IORequest*)ioreq);
  448. }
  449.  
  450. /****************************************************************************/
  451. /*
  452.  * Prevents DOS to access a DFx device.
  453.  */
  454. static int dev_inhibit(char *dev,int on)
  455. {
  456.     char buff[10],*s;
  457.     struct MsgPort *DevPort;
  458.  
  459.     if(!*dev) return 0;
  460.     s=dev;while(*s++);
  461.     if(s[-2]==':') strcpy(buff,dev); else sprintf(buff,"%s:",dev);
  462.     if((DevPort = (struct MsgPort*)DeviceProc((STRPTR)buff))) {
  463.         if(on) {
  464.            DoPkt(DevPort,ACTION_INHIBIT,DOSTRUE,NULL,NULL,NULL,NULL);
  465.            return 1;
  466.         }
  467.         else   DoPkt(DevPort,ACTION_INHIBIT,DOSFALSE,NULL,NULL,NULL,NULL);
  468.     }
  469.     return 0;
  470. }
  471.  
  472.